﻿using System;
using System.Linq;
using System.Reflection;
using Microsoft.Office.Server.SocialData;
using Microsoft.Office.Server.UserProfiles;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace SPSocialTagCounters.Helpers
{
    public class SPSocialTagCounter
    {
        public int Tags { get; set; }
        public string TagsList { get; set; }
        public int Likes { get; set; }
        public string LikesList { get; set; }
    }
    
    public class SocialHelper
    {
        private static MethodInfo GetSocialMethod()
        {
            var type = typeof(SocialTagManager);
            var methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Instance);
            var method = methods.FirstOrDefault(m => m.ToString() == "Microsoft.Office.Server.SocialData.SocialTag[] GetTags(System.Uri, Int32, Microsoft.Office.Server.SocialData.SocialItemPrivacy)");
            return method;
        }

        private static string CreateLikesList(SocialTag[] itemTags)
        {
            string likesText = "";
            var socialTags = itemTags.Where(t => t.Term.Name.ToLower() == "i like it");
            foreach (var socialTag in socialTags)
            {
                var user = socialTag.Owner;
                string personalSite = user.PublicUrl.AbsoluteUri;
                likesText += string.Format("<a href='{0}' title='{1}'>{1}</a>", personalSite, user.DisplayName);
            }
            return likesText;
        }

        private static string CreateTagsList(SocialTag[] itemTags, string tagProfileURL)
        {
            string tagsText = "";
            // Grouping tags
            var socialTerms = itemTags
                .Where(t => t.Term.Name.ToLower() != "i like it")
                .OrderBy(t => t.Term.Name)
                .GroupBy(t => t.Term)
                .Select(g => new { tag = g.Key, count = g.Count() });

            foreach (var socialTag in socialTerms)
            {
                tagsText += string.Format("<a href='{0}{1}' title='{2}'>{2} ({3})</a>", tagProfileURL, socialTag.tag.Id.ToString("D"), socialTag.tag.Name, socialTag.count);
            }

            return tagsText;
        }

        public static SPSocialTagCounter GetTags(Uri pageRequest)
        {
            SPSocialTagCounter socialTagCounter = new SPSocialTagCounter();

            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    using (SPSite site = new SPSite(SPContext.Current.Web.Url))
                    using (SPWeb web = site.OpenWeb())
                    {                   
                        // Retrieve the Internal Social Tag Method
                        var method = GetSocialMethod();

                        if (method != null)
                        {
                            SPServiceContext serviceContext = SPServiceContext.GetContext(site);
                            SocialTagManager stm = new SocialTagManager(serviceContext);

                            // Get page URL
                            Uri uri = pageRequest;
                            // Check if it is a blog post
                            if (-1 == uri.AbsoluteUri.IndexOf("post.aspx", StringComparison.OrdinalIgnoreCase))
                            {
                                // Check if page is welcome page
                                string root = web.RootFolder.WelcomePage;
                                // Check if welcome page is not empty
                                if (!string.IsNullOrEmpty(root))
                                {
                                    if (uri.AbsoluteUri.Contains(root))
                                    {
                                        uri = new Uri(SPContext.Current.Web.Url);
                                    }
                                }
                            }
                            else
                            {
                                // When it is a blog post, the url needs to be changed
                                uri = new Uri(uri.AbsoluteUri.Replace("Post.aspx", "ViewPost.aspx"));
                            }

                            // Retrieve only the public tags
                            var itemTags = (SocialTag[])method.Invoke(stm, new object[] { uri, 1000, SocialItemPrivacy.PublicOnly });
                            
                            socialTagCounter.Likes = itemTags.Count(t => t.Term.Name.ToLower() == "i like it");
                            socialTagCounter.Tags = itemTags.Count(t => t.Term.Name.ToLower() != "i like it");

                            if (socialTagCounter.Likes > 0)
                            {
                                socialTagCounter.LikesList = CreateLikesList(itemTags);
                            }

                            if (socialTagCounter.Tags > 0)
                            {
                                // Retrieve the My Site host location
                                UserProfileManager userProfileManager = new UserProfileManager();
                                string mySiteHostUrl = userProfileManager.MySiteHostUrl;

                                // Create the tag profile URL
                                string tagProfileURL = string.Concat(mySiteHostUrl, "tagprofile.aspx?TermID=");

                                // Create tags list
                                socialTagCounter.TagsList = CreateTagsList(itemTags, tagProfileURL);
                            }
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                SPDiagnosticsCategory diagnosticsCategory = new SPDiagnosticsCategory("SPSocialTagCounters", TraceSeverity.Unexpected, EventSeverity.Error);
                SPDiagnosticsService.Local.WriteTrace(0, diagnosticsCategory, TraceSeverity.Unexpected, ex.Message, ex.StackTrace);
            }

            return socialTagCounter;
        }

    }
}
